package com.example.jobback.service.seeker.impl;

import com.alibaba.fastjson.JSON;
import com.example.jobback.common.enums.Edu;
import com.example.jobback.config.AuthConfig;
import com.example.jobback.mapper.CompanyMapper;
import com.example.jobback.mapper.PositionMapper;
import com.example.jobback.mapper.SeekerMapper;
import com.example.jobback.po.Seeker;
import com.example.jobback.po.User;
import com.example.jobback.req.common.page.PageReq;
import com.example.jobback.req.recruiter.position.search.RCrossSearchJobOrCompanyReq;
import com.example.jobback.req.seeker.genius.SCrossGetGoodSeekerListReq;
import com.example.jobback.req.seeker.search.SearchJobOrCompanyReq;
import com.example.jobback.resp.recruiter.position.search.RCrossSearchCompany;
import com.example.jobback.resp.recruiter.position.search.RCrossSearchJobOrCompanyResp;
import com.example.jobback.resp.recruiter.position.search.RCrossSearchPosition;
import com.example.jobback.resp.recruiter.profile.RecruiterCompanyResp;
import com.example.jobback.resp.seeker.common.SCrossSeekerResp;
import com.example.jobback.resp.seeker.common.page.SCrossGetPageSeekerResp;
import com.example.jobback.resp.seeker.common.page.SCrossGetPageSeekersResp;
import com.example.jobback.resp.seeker.genius.SCrossGetGoodSeekerResp;
import com.example.jobback.resp.seeker.genius.SCrossGetGoodSeekersResp;
import com.example.jobback.resp.seeker.profile.SCrossRecruiterCompanyResp;
import com.example.jobback.resp.seeker.search.SCrossSearchJobOrCompanyResp;
import com.example.jobback.resp.seeker.search.SearchCompanyResp;
import com.example.jobback.resp.seeker.search.SearchJobResp;
import com.example.jobback.result.Result;
import com.example.jobback.service.common.UserCommonService;
import com.example.jobback.service.seeker.SeekerCommonService;
import com.example.jobback.util.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.*;

import static com.example.jobback.util.RedisConstants.SEEKER_KEY;

/**
 * @ClassName: SeekerCommonServiceImpl
 * @Description:求职者-通用实现类
 * @Author: lhb
 * @Date: 2025/6/21
 */
@Service
public class SeekerCommonServiceImpl implements SeekerCommonService {


    private final CACHEUtil cacheUtil;


    private final SeekerMapper seekerMapper;

    private final PhoneNumberUtils phoneNumberUtils;

    private final AuthConfig authConfig;

    private final RestTemplate restTemplate;

    private final UserCommonService userCommonService;

    private final CompanyMapper companyMapper;

    private final PositionMapper positionMapper;

    @Value("${cross_service_baseurl}")
    private String crossServiceBaseUrl;

    public SeekerCommonServiceImpl(AuthConfig authConfig, RestTemplate restTemplate, PositionMapper positionMapper, CompanyMapper companyMapper, CACHEUtil cacheUtil, SeekerMapper seekerMapper, UserCommonService userCommonService, PhoneNumberUtils phoneNumberUtils) {
        this.authConfig = authConfig;
        this.restTemplate = restTemplate;
        this.positionMapper = positionMapper;
        this.companyMapper = companyMapper;
        this.cacheUtil = cacheUtil;
        this.seekerMapper = seekerMapper;
        this.userCommonService = userCommonService;
        this.phoneNumberUtils = phoneNumberUtils;
    }


    /**
     * @Description: 跨服务调用，获取招聘者基本信息
     * @param userId
     * @return Result<CrossRecruiterCompanyResp>
     * @Author lhb
     * @CreateTime 2025/6/21 14:32
     */
    @Override
    public Result<SCrossRecruiterCompanyResp> getRecruiterBasicMessage(Long userId) {
        Map<String, Object> params = new HashMap<>();
        params.put("userId", userId);
        String url = crossServiceBaseUrl + "/recruiter/company/getRecruiterBasicMessage";
        // 手动创建 CrossServiceInvoker 实例
        CrossServiceInvoker invoker =
                new CrossServiceInvoker(authConfig, restTemplate);
        Result<RecruiterCompanyResp> result = null;
        try {
            result = invoker.invokeAndHandle(
                    url,
                    HttpMethod.POST,
                    null,
                    RecruiterCompanyResp.class,
                    userId,
                    params
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!result.getCode().equals(HttpServletResponse.SC_CREATED)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：无此用户招聘端信息");
        }
        SCrossRecruiterCompanyResp resp=new SCrossRecruiterCompanyResp();
        BeanUtils.copyProperties(result.getData(), resp);
        return Result.success(resp);
    }

    /**
     * @Description: 搜索功能，跨服务调用方
     * @param req
     * @return Result<SCrossSearchJobOrCompanyResp>
     * @Author lhb
     * @CreateTime 2025/6/26 10:13
     */
    @Override
    public Result<SCrossSearchJobOrCompanyResp> searchJobOrCompany(SearchJobOrCompanyReq req) {
        Seeker seeker=TLUtil.get(TLUtil.S);
        Long userId=seeker.getUserId();
        SCrossSearchJobOrCompanyResp resp=new SCrossSearchJobOrCompanyResp();
        resp.setCompanyRespList(new ArrayList<>());
        resp.setJobRespList(new ArrayList<>());
        RCrossSearchJobOrCompanyReq rCrossSearchJobOrCompanyReq=new RCrossSearchJobOrCompanyReq();
        BeanUtils.copyProperties(req,rCrossSearchJobOrCompanyReq);
        rCrossSearchJobOrCompanyReq.setSeeker(seeker);
        //跨服务调用
        RCrossSearchJobOrCompanyResp crossResp=crossSearchJobOrCompany(rCrossSearchJobOrCompanyReq,userId);
        //类型转换
        if(!crossResp.getRCrossSearchCompanyList().isEmpty()){
            for(RCrossSearchCompany rCompanyResp:crossResp.getRCrossSearchCompanyList()){
                SearchCompanyResp companyResp=new SearchCompanyResp();
                BeanUtils.copyProperties(rCompanyResp,companyResp);
                resp.getCompanyRespList().add(companyResp);
            }
        }
        if(!crossResp.getRCrossSearchPositionList().isEmpty()){
            for (RCrossSearchPosition rPositionResp:crossResp.getRCrossSearchPositionList()){
                SearchJobResp jobResp=new SearchJobResp();
                BeanUtils.copyProperties(rPositionResp,jobResp);
                resp.getJobRespList().add(jobResp);
            }
        }
        return Result.success(resp);
    }

    /**
     * @Description: 跨服务调用搜索功能
     * @param rCrossSearchJobOrCompanyReq
     * @return RCrossSearchJobOrCompanyResp
     * @Author lhb
     * @CreateTime 2025/6/26 10:17
     */
    private RCrossSearchJobOrCompanyResp crossSearchJobOrCompany(RCrossSearchJobOrCompanyReq rCrossSearchJobOrCompanyReq,
                                                                 Long userId) {
        String url = crossServiceBaseUrl + "/recruiter/position/searchJobOrCompany";
        // 手动创建 CrossServiceInvoker 实例
        CrossServiceInvoker invoker =
                new CrossServiceInvoker(authConfig, restTemplate);
        Result<Object> result = null;
        try {
            result = invoker.invokeAndHandle(
                    url,
                    HttpMethod.POST,
                    rCrossSearchJobOrCompanyReq,
                    Object.class,
                    userId,
                    null
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!result.getCode().equals(HttpServletResponse.SC_CREATED)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：查询错误");
        }
        return JSON.parseObject(JSON.toJSONString(result.getData()),
                RCrossSearchJobOrCompanyResp.class);
    }

    /**
     * @Description: 跨服务，被调用方，获取指定求职者基本信息,求职者和招聘者使用
     * @param userId
     * @return Result<SCrossSeekerResp>
     * @Author lhb
     * @CreateTime 2025/6/25 9:28
     */
    @Override
    public Result<SCrossSeekerResp> getSeekerBasicMessage(Long userId) {
        Seeker seeker=getSeekerMessage(userId);
        SCrossSeekerResp resp=processSeekerMessage(seeker);
        //电话号码带*处理
        String maskedPhone = PhoneNumberUtils.maskPhoneNumber(resp.getPhone());
        resp.setPhone(maskedPhone);
        return Result.success(resp);
    }

    /**
     * @Description: 构造求职者信息响应体
     * @param seeker
     * @return SCrossSeekerResp
     * @Author lhb
     * @CreateTime 2025/7/3 21:35
     */
    private SCrossSeekerResp processSeekerMessage(Seeker seeker) {
        String phone = null;
        try {
            phone = SecureEncryptionUtil.decrypt(seeker.getPhoneAes(), authConfig.getPhoneSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        SCrossSeekerResp resp=new SCrossSeekerResp();
        Long age=0L;
        LocalDateTime birthDate=seeker.getBirthDate();
        if (birthDate!=null) {
            age = (long) Period.between(LocalDate.from(birthDate), LocalDate.now()).getYears();
        }
        resp.setAge(age);
        resp.setPhone(phone);
        BeanUtils.copyProperties(seeker, resp);
        return resp;
    }

    /**
     * @Description: 共用代码，获取指定userid的求职者信息
     * @param userId
     * @return Seeker
     * @Author lhb
     * @CreateTime 2025/7/3 21:34
     */
    private Seeker getSeekerMessage(Long userId) {
        //在redis查看用户
        String key=SEEKER_KEY+userId.toString();
        Map<Object,Object> userMap=cacheUtil.getHash(key);
        Seeker seeker=null;
        if(userMap.isEmpty()){
            seeker = seekerMapper.getSeekerByUserId(userId);
            if(seeker == null) {
                throw new IllegalArgumentException("VALIDATION_ERROR：无此用户招聘端信息");
            }
            User user=userCommonService.getUserByUserId(userId);
            BeanUtils.copyProperties(user, seeker);
        }else {
            // 从 Redis 获取用户 JSON 数据
            String userJson = (String) userMap.get("user");
            //反序列化
            seeker = JSON.parseObject(userJson, Seeker.class);
            if(seeker ==null){
                throw new RuntimeException("缓存查询异常");
            }
        }
        return seeker;
    }


    /**
     * @Description: 跨服务被调用方，获取求职者列表
     * @param pageReq
     * @return Result<SCrossGetPageSeekersResp>
     * @Author lhb
     * @CreateTime 2025/7/4 15:27
     */
    @Override
    public Result<SCrossGetPageSeekersResp> getSeekers(PageReq pageReq) {
        String content = pageReq.getContent();
        int page = pageReq.getPage();
        int size = pageReq.getSize();
        if(content.isEmpty()){
            PageHelper.startPage(page, size);
            List<Seeker> seekers=seekerMapper.getSeekers();
            //获取页的相关信息
            PageInfo<Seeker> seekerPageInfo = new PageInfo<>(seekers);
            //获取userid查找user对象
            List<Long> userIds = seekers.stream()
                    .map(Seeker::getUserId)
                    .filter(Objects::nonNull)
                    .toList();
            List<User> users=userCommonService.getUsersByUserIds(userIds);
            //处理分页查询管理员列表响应体
            SCrossGetPageSeekersResp resp=processPageSeekerList(seekers, users,seekerPageInfo);
            return Result.success(resp);
        }
        List<User> users=userCommonService.getUsersByName(content);
        if(users.isEmpty()){
            SCrossGetPageSeekersResp resp = new SCrossGetPageSeekersResp();
            resp.setPages(0);
            resp.setTotal(0L);
            resp.setPageNum(0);
            resp.setPageSize(0);
            resp.setSize(0);
            resp.setRespList(new ArrayList<>());
            return Result.success(resp);
        }
        List<Long> userIds = users.stream()
                .map(User::getUserId)
                .filter(Objects::nonNull)
                .toList();
        PageHelper.startPage(page, size);
        List<Seeker> seekers=seekerMapper.getSeekerByUserIds(userIds);
        //获取页的相关信息
        PageInfo<Seeker> seekerPageInfo = new PageInfo<>(seekers);
        //处理分页查询管理员列表响应体
        SCrossGetPageSeekersResp resp=processPageSeekerList(seekers, users,seekerPageInfo);
        return Result.success(resp);
    }

    /**
     * @Description: 跨服务调用，被调用方，管理员端使用
     * @param userId
     * @return Result<SCrossSeekerResp>
     * @Author lhb
     * @CreateTime 2025/7/3 21:33
     */
    @Override
    public Result<SCrossSeekerResp> getSeekerBasicMessageForAdmin(Long userId) {
        Seeker seeker=getSeekerMessage(userId);
        SCrossSeekerResp resp=processSeekerMessage(seeker);
        return Result.success(resp);
    }

    /**
     * @Description: 获取推荐牛人列表，被调用方
     * @param req
     * @return Result<List<SCrossGetGoodSeekerResp>>
     * @Author lhb
     * @CreateTime 2025/7/9 11:34
     */
    @Override
    public Result<SCrossGetGoodSeekersResp> getGoodSeekerList(SCrossGetGoodSeekerListReq req) {
        //根据职位，其次行业
        List<Edu> eduList = req.getEduList();
        String industry = req.getIndustry();
        String positionName = req.getPositionName();
        Long lowestSalaryMonth = req.getLowestSalaryMonth();
        Long highestSalaryMonth = req.getHighestSalaryMonth();
        List<Long> recruiterUserIdList = req.getRecruiterUserIdList();
        int page = req.getPage();
        int size = req.getSize();
        PageHelper.startPage(page, size);
        List<Seeker> seekerList = seekerMapper.getGoodSeekerList(industry,positionName,eduList,
                lowestSalaryMonth,highestSalaryMonth, recruiterUserIdList);
        PageInfo<Seeker> seekerPageInfo = new PageInfo<>(seekerList);
        if(seekerList.isEmpty()){
            SCrossGetGoodSeekersResp resp = new SCrossGetGoodSeekersResp();
            resp.setPages(0);
            resp.setTotal(0L);
            resp.setPageNum(0);
            resp.setPageSize(0);
            resp.setSize(0);
            resp.setRespList(new ArrayList<>());
            return Result.success(resp);
        }
        List<Long> userIds = seekerList.stream()
                .map(Seeker::getUserId)
                .filter(Objects::nonNull)
                .toList();
        List<User> userList=userCommonService.getUsersByUserIds(userIds);
        SCrossGetGoodSeekersResp resp=processGoodSeekerList(seekerList, userList,seekerPageInfo);
        return Result.success(resp);
    }

    /**
     * @Description: 使用stream.map等处理分页查询推荐牛人列表响应体
     * @param seekerList
     * @param userList
     * @param seekerPageInfo
     * @return SCrossGetGoodSeekersResp
     * @Author lhb
     * @CreateTime 2025/7/9 15:37
     */
    private SCrossGetGoodSeekersResp processGoodSeekerList(List<Seeker> seekerList, List<User> userList,
                                                           PageInfo<Seeker> seekerPageInfo) {
        //初始化响应体
        SCrossGetGoodSeekersResp resp=new SCrossGetGoodSeekersResp();
        resp.setRespList(new ArrayList<>());
        // 使用 Stream 和 map 方法进行映射
        List<Seeker> mappedSeekers = seekerList.stream()
                .map(seeker -> {
                    // 找到对应的 User
                    userList.stream()
                            .filter(u -> u.getUserId().equals(seeker.getUserId()))
                            .findFirst().ifPresent(user -> BeanUtils.copyProperties(user, seeker));
                    return seeker;
                })
                .toList();
        //构造响应体
        resp.setPages(seekerPageInfo.getPages());
        resp.setTotal(seekerPageInfo.getTotal());
        resp.setPageNum(seekerPageInfo.getPageNum());
        resp.setPageSize(seekerPageInfo.getPageSize());
        resp.setSize(seekerPageInfo.getSize());
        List<Seeker> pageSeekerList=seekerPageInfo.getList();
        for (Seeker seeker:pageSeekerList){
            String phone="";
            try {
                phone=phoneNumberUtils.decryptPhone(seeker.getPhoneAes());
                phone=PhoneNumberUtils.maskPhoneNumber(phone);
            } catch (Exception e) {
                throw new RuntimeException("电话号码格式有误，解密失败");
            }
            SCrossGetGoodSeekerResp seekerResp=new SCrossGetGoodSeekerResp();
            BeanUtils.copyProperties(seeker,seekerResp);
            seekerResp.setPhone(phone);
            resp.getRespList().add(seekerResp);
        }
        return resp;
    }

    /**
     * @Description: 使用stream.map等处理分页查询求职者列表响应体
     * @param seekers
     * @param users
     * @param seekerPageInfo
     * @return SCrossGetPageSeekersResp
     * @Author lhb
     * @CreateTime 2025/7/3 11:43
     */
    private SCrossGetPageSeekersResp processPageSeekerList(List<Seeker> seekers,
                                                           List<User> users,
                                                           PageInfo<Seeker> seekerPageInfo) {
        //初始化响应体
        SCrossGetPageSeekersResp resp=new SCrossGetPageSeekersResp();
        resp.setRespList(new ArrayList<>());
        // 使用 Stream 和 map 方法进行映射
        List<Seeker> mappedSeekers = seekers.stream()
                .map(seeker -> {
                    // 找到对应的 User
                    users.stream()
                            .filter(u -> u.getUserId().equals(seeker.getUserId()))
                            .findFirst().ifPresent(user -> BeanUtils.copyProperties(user, seeker));
                    return seeker;
                })
                .toList();
        //构造响应体
        resp.setPages(seekerPageInfo.getPages());
        resp.setTotal(seekerPageInfo.getTotal());
        resp.setPageNum(seekerPageInfo.getPageNum());
        resp.setPageSize(seekerPageInfo.getPageSize());
        resp.setSize(seekerPageInfo.getSize());
        List<Seeker> pageSeekerList=seekerPageInfo.getList();
        for (Seeker seeker:pageSeekerList){
            String phone="";
            try {
                phone=phoneNumberUtils.decryptPhone(seeker.getPhoneAes());
            } catch (Exception e) {
                throw new RuntimeException("电话号码格式有误，解密失败");
            }
            SCrossGetPageSeekerResp seekerResp=new SCrossGetPageSeekerResp();
            BeanUtils.copyProperties(seeker,seekerResp);
            seekerResp.setPhone(phone);
            resp.getRespList().add(seekerResp);
        }
        return resp;
    }
}
